from __future__ import annotations

"""
对账与回抄服务
--------------
D5 阶段：周期性调用 MCP 查询订单状态、成交明细，回填 orders/fills
"""

import datetime as dt
import json
import logging
from decimal import Decimal
from typing import List, Optional

from sqlalchemy import and_, select
from sqlalchemy.ext.asyncio import AsyncSession

from ..models import Fill, TradingOrder
from ..services.mcp_session import mcp

logger = logging.getLogger(__name__)


async def reconcile_orders(
    session: AsyncSession,
    order_ids: Optional[List[str]] = None,
    exchange: Optional[str] = None,
) -> int:
    """对账：查询订单状态和成交，更新数据库"""
    await mcp.start()
    
    if not mcp.enabled:
        logger.warning("MCP 服务未启用，跳过对账")
        return 0
    
    # 获取待对账订单
    stmt = select(TradingOrder)
    conditions = []
    if order_ids:
        conditions.append(TradingOrder.order_id.in_(order_ids))
    if exchange:
        conditions.append(TradingOrder.exchange == exchange)
    if conditions:
        stmt = stmt.where(and_(*conditions))
    
    # 只对账未完成的订单
    stmt = stmt.where(
        TradingOrder.status.in_(["sent", "partial", "pending"])
    ).limit(100)
    
    result = await session.execute(stmt)
    orders = result.scalars().all()
    
    updated_count = 0
    
    for order in orders:
        try:
            # 查询订单状态
            from ..routers.ai import _flatten_mcp_result
            
            # 调用 get_open_orders 或 get_order_history
            try:
                order_result = await mcp.call_tool("get_open_orders", {
                    "exchange": order.exchange
                })
                order_text = _flatten_mcp_result(order_result)
                orders_data = json.loads(order_text) if order_text else []
                
                # 查找当前订单
                current_order = None
                for o in orders_data:
                    if o.get("order_id") == order.order_id or o.get("client_order_id") == order.client_order_id:
                        current_order = o
                        break
                
                if current_order:
                    # 更新订单状态
                    order.status = current_order.get("status", order.status)
                    order.raw = current_order
                    
                    # 如果有成交信息，创建 fills
                    fills_data = current_order.get("fills", [])
                    for fill_data in fills_data:
                        # 检查是否已存在（去重）
                        existing_stmt = select(Fill).where(
                            and_(
                                Fill.order_id == order.order_id,
                                Fill.price == Decimal(str(fill_data.get("price", 0))),
                                Fill.qty == Decimal(str(fill_data.get("qty", 0))),
                            )
                        )
                        existing_result = await session.execute(existing_stmt)
                        if not existing_result.scalar_one_or_none():
                            fill = Fill(
                                order_id=order.order_id,
                                price=Decimal(str(fill_data.get("price", 0))),
                                qty=Decimal(str(fill_data.get("qty", 0))),
                                fee=Decimal(str(fill_data.get("fee", 0))) if fill_data.get("fee") else None,
                                fee_asset=fill_data.get("fee_asset"),
                            )
                            session.add(fill)
                    
                    updated_count += 1
                else:
                    # 订单可能已完成，查询历史
                    history_result = await mcp.call_tool("get_order_history", {
                        "exchange": order.exchange,
                        "trading_pair": order.symbol,
                        "limit": 10
                    })
                    history_text = _flatten_mcp_result(history_result)
                    history_data = json.loads(history_text) if history_text else []
                    
                    for h in history_data:
                        if h.get("order_id") == order.order_id:
                            order.status = h.get("status", "filled")
                            order.raw = h
                            updated_count += 1
                            break
                
            except Exception as e:
                logger.warning(f"查询订单 {order.order_id} 失败: {e}")
                continue
            
            await session.commit()
            
        except Exception as e:
            logger.error(f"对账订单 {order.order_id} 时出错: {e}")
            await session.rollback()
            continue
    
    logger.info(f"对账完成: 更新了 {updated_count} 个订单")
    return updated_count


async def calculate_daily_pnl(
    session: AsyncSession,
    day: Optional[dt.date] = None,
    run_id: Optional[str] = None,
) -> None:
    """D6 阶段：计算日度 PnL 并写入 pnl_daily"""
    from ..models import PnLDaily
    
    if not day:
        day = dt.date.today()
    
    # 获取该日期的所有订单和成交
    start_time = dt.datetime.combine(day, dt.time.min).replace(tzinfo=dt.timezone.utc)
    end_time = dt.datetime.combine(day, dt.time.max).replace(tzinfo=dt.timezone.utc)
    
    conditions = [
        TradingOrder.created_at >= start_time,
        TradingOrder.created_at <= end_time,
    ]
    if run_id:
        conditions.append(TradingOrder.run_id == run_id)
    
    stmt = select(TradingOrder).where(and_(*conditions))
    result = await session.execute(stmt)
    orders = result.scalars().all()
    
    # 计算已实现盈亏（基于成交）
    realized = Decimal("0")
    order_ids = [o.order_id for o in orders]
    
    if order_ids:
        fills_stmt = select(Fill).where(Fill.order_id.in_(order_ids))
        fills_result = await session.execute(fills_stmt)
        fills = fills_result.scalars().all()
        
        # 按订单计算盈亏
        for order in orders:
            order_fills = [f for f in fills if f.order_id == order.order_id]
            if not order_fills:
                continue
            
            # 简化计算：假设都是买入或卖出，基于成交价和当前价
            # 实际应该用更复杂的逻辑
            total_cost = sum(Decimal(str(f.price)) * Decimal(str(f.qty)) for f in order_fills)
            total_fees = sum(Decimal(str(f.fee)) for f in order_fills if f.fee)
            
            if order.side == "sell":
                # 卖出，实现盈利
                realized += total_cost - total_fees
            else:
                # 买入，成本
                realized -= total_cost + total_fees
    
    # 计算未实现盈亏（基于持仓和最新价）
    # 这里需要获取最新快照
    unrealized = Decimal("0")
    
    # 获取最新快照
    if run_id:
        from ..models import Snapshot
        snapshot_stmt = (
            select(Snapshot)
            .where(Snapshot.run_id == run_id)
            .order_by(Snapshot.ts.desc())
            .limit(1)
        )
        snapshot_result = await session.execute(snapshot_stmt)
        snapshot = snapshot_result.scalar_one_or_none()
        
        if snapshot:
            positions = snapshot.payload.get("positions", {})
            ticker = snapshot.payload.get("ticker", {})
            last_price = Decimal(str(ticker.get("last", 0)))
            
            # 简化计算：基于持仓和当前价
            for pos_symbol, pos_data in positions.items():
                if isinstance(pos_data, dict):
                    size = Decimal(str(pos_data.get("size", 0)))
                    side = pos_data.get("side", "long")
                    entry_price = Decimal(str(pos_data.get("entry_price", 0)))
                    
                    if entry_price and last_price:
                        if side == "long":
                            unrealized += (last_price - entry_price) * size
                        else:
                            unrealized += (entry_price - last_price) * size
    
    # Upsert pnl_daily
    from ..models import PnLDaily
    
    stmt = select(PnLDaily).where(
        and_(PnLDaily.day == day, PnLDaily.run_id == run_id if run_id else True)
    )
    result = await session.execute(stmt)
    existing = result.scalar_one_or_none()
    
    if existing:
        existing.realized = realized
        existing.unrealized = unrealized
        existing.updated_at = dt.datetime.now(dt.timezone.utc)
    else:
        if run_id:
            pnl = PnLDaily(
                day=day,
                run_id=run_id,
                realized=realized,
                unrealized=unrealized,
            )
            session.add(pnl)
    
    await session.commit()
    logger.info(f"PnL 计算完成: day={day}, run_id={run_id}, realized={realized}, unrealized={unrealized}")

